home *** CD-ROM | disk | FTP | other *** search
/ The World's Largest Collection of Windows Software / The World's Largest Collection of Windows Software - Disc 1.iso / connect / _j2 / wvnsc926 / rcs / wvblock.c < prev    next >
C/C++ Source or Header  |  1994-09-21  |  61KB  |  2,049 lines

  1. head     1.9;
  2. branch   ;
  3. access   ;
  4. symbols  V80:1.2 V76d:1.1;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.9
  10. date     94.09.16.00.47.44;  author jcooper;  state Exp;
  11. branches ;
  12. next     1.8;
  13.  
  14. 1.8
  15. date     94.08.23.23.09.33;  author martin;  state Exp;
  16. branches ;
  17. next     1.7;
  18.  
  19. 1.7
  20. date     94.06.08.21.01.45;  author gardnerd;  state Exp;
  21. branches ;
  22. next     1.6;
  23.  
  24. 1.6
  25. date     94.06.01.19.04.02;  author gardnerd;  state Exp;
  26. branches ;
  27. next     1.5;
  28.  
  29. 1.5
  30. date     94.01.12.19.27.32;  author mrr;  state Exp;
  31. branches ;
  32. next     1.4;
  33.  
  34. 1.4
  35. date     93.12.08.01.27.21;  author rushing;  state Exp;
  36. branches ;
  37. next     1.3;
  38.  
  39. 1.3
  40. date     93.06.28.17.53.24;  author rushing;  state Exp;
  41. branches ;
  42. next     1.2;
  43.  
  44. 1.2
  45. date     93.05.24.23.56.18;  author rushing;  state Exp;
  46. branches ;
  47. next     1.1;
  48.  
  49. 1.1
  50. date     93.02.16.20.53.50;  author rushing;  state Exp;
  51. branches ;
  52. next     ;
  53.  
  54.  
  55. desc
  56. @winvn version 0.76 placed into RCS
  57. @
  58.  
  59.  
  60. 1.9
  61. log
  62. @Rearrange headers to allow precompiled headers
  63. @
  64. text
  65. @
  66. /*
  67.  *
  68.  * $Id: wvblock.c 1.8 1994/08/23 23:09:33 martin Exp $
  69.  * $Log: wvblock.c $
  70.  * Revision 1.8  1994/08/23  23:09:33  martin
  71.  * movebytes param changed from far * to huge *
  72.  *
  73.  * Revision 1.7  1994/06/08  21:01:45  gardnerd
  74.  * more scrolling changes...
  75.  *
  76.  * Revision 1.6  1994/06/01  19:04:02  gardnerd
  77.  * horizontal scrolling support
  78.  *
  79.  * Revision 1.5  1994/01/12  19:27:32  mrr
  80.  * mrr mods 4
  81.  *
  82.  * Revision 1.4  1993/12/08  01:27:21  rushing
  83.  * new version box and cr lf consistency
  84.  *
  85.  * Revision 1.3  1993/06/28  17:53:24  rushing
  86.  * fixed compiler warnings
  87.  *
  88.  * Revision 1.2  1993/05/24  23:56:18  rushing
  89.  * Doc->HeaderLines = 0 (MRB)
  90.  *
  91.  * Revision 1.1  1993/02/16  20:53:50  rushing
  92.  * Initial revision
  93.  *
  94.  *
  95.  */
  96.  
  97. /* -- WVBLOCK.C --------------------------------------------------
  98.  *
  99.  *  This file contains a collection of routines to manipulate textblocks
  100.  *  and lines within textblocks.
  101.  *  The routines here view lines as atomic units only (they don't
  102.  *  look at the actual data in the lines).
  103.  *
  104.  *  Mark Riordan   20 September 1989.
  105.  */
  106.  
  107. #include <windows.h>
  108. #include <windowsx.h>
  109. #include "wvglob.h"
  110. #include "winvn.h"
  111. #pragma hdrstop
  112. #include <ctype.h>
  113.  
  114. /*-- function NewBlock ------------------------------------------
  115.  *
  116.  *  Creates an empty, new textblock and links it into the list
  117.  *  of blocks after a given block.
  118.  *  After the call, both the old ("given") block and the new block
  119.  *  are locked in memory.
  120.  *
  121.  *    Entry    CurBlockPtr    points to a block
  122.  *
  123.  *    Exit     NewBlockPtr    points to a block that has been linked
  124.  *                            into the list just after CurBlockPtr.
  125.  *             Returns TRUE if couldn't allocate a block, else FALSE.
  126.  *             (I know I should fix that.)
  127.  */
  128. int
  129. NewBlock (CurBlockPtr, NewBlockPtr)
  130.      TypBlock far *CurBlockPtr, far ** NewBlockPtr;
  131. {
  132.   HANDLE hMyBlock;
  133.   TypBlock far *MyBlock, far * MyNextBlock;
  134.  
  135.   hMyBlock = GlobalAlloc (GMEM_MOVEABLE, (long) (CurBlockPtr->OwnerDoc->BlockSize));
  136.   if (hMyBlock)
  137.     {
  138.       MyBlock = (TypBlock far *) GlobalLock (hMyBlock);
  139.       SetupEmptyBlock (MyBlock, hMyBlock, CurBlockPtr->hCurBlock,
  140.              CurBlockPtr->hNextBlock, CurBlockPtr->OwnerDoc);
  141.       CurBlockPtr->hNextBlock = hMyBlock;
  142.  
  143.       /* Change the next block's "previous" pointer to point to us. */
  144.  
  145.       if (MyBlock->hNextBlock)
  146.    {
  147.      MyNextBlock = (TypBlock far *) GlobalLock (MyBlock->hNextBlock);
  148.      MyNextBlock->hPrevBlock = hMyBlock;
  149.      GlobalUnlock (MyBlock->hNextBlock);
  150.    }
  151.  
  152.       *NewBlockPtr = MyBlock;
  153.     }
  154.   else
  155.     {
  156.       MessageBox (CurBlockPtr->OwnerDoc->hDocWnd, "Could not allocate textblock", "Out of Memory Error", MB_OK | MB_ICONHAND);
  157.       return (1);
  158.     }
  159.   return (0);
  160. }
  161.  
  162. /*-- function SetupEmptyBlock -----------------------------------------
  163.  *
  164.  *  Initialize fields in a newly-allocated textblock.
  165.  *  Set the fields to indicate an empty block.
  166.  */
  167. void
  168. SetupEmptyBlock (BlockPtr, hCur, hPrev, hNext, DocPtr)
  169.      TypBlock far *BlockPtr;
  170.      HANDLE hCur, hPrev, hNext;
  171.      TypDoc *DocPtr;
  172. {
  173.   BlockPtr->OwnerDoc = DocPtr;
  174.   BlockPtr->hCurBlock = hCur;
  175.   BlockPtr->hPrevBlock = hPrev;
  176.   BlockPtr->hNextBlock = hNext;
  177.   BlockPtr->LWAp1 = sizeof (TypBlock) + sizeof (TypLine);
  178.   BlockPtr->NumLines = 0;
  179.   BlockPtr->NumActiveLines = 0;
  180.   BlockPtr->eob = END_OF_BLOCK;
  181.   ((TypLine far *) ((char far *) BlockPtr + sizeof (TypBlock)))->length = END_OF_BLOCK;
  182.   ((TypLine far *) ((char far *) BlockPtr + sizeof (TypBlock)))->LineID = NextLineID++;
  183. }
  184.  
  185. /*-- function DeleteBlock ---------------------------------------------
  186.  *
  187.  *  Delete a textblock from a document.
  188.  *
  189.  *    Entry    CurBlockPtr points to the block to delete.
  190.  *
  191.  *    Exit     CurBlockPtr points to the next block, if any, else the
  192.  *                         previous block.
  193.  *             CurLinePtr  points to the first line of the next block
  194.  *                         if there was one, else the last line of
  195.  *                         the previous block.
  196.  */
  197. BOOL
  198. DeleteBlock (TypBlock far ** CurBlockPtr, TypLine far ** CurLinePtr)
  199. {
  200.   TypBlock far *MyBlockPtr = *CurBlockPtr;
  201.   TypBlock far *BlockPtr;
  202.   HANDLE hMyBlock = MyBlockPtr->hCurBlock, hMyPrev = MyBlockPtr->hPrevBlock, hMyNext = MyBlockPtr->hNextBlock;
  203.   BOOL set_cur_block = FALSE;
  204.  
  205.   /* Don't delete the only block in the document. */
  206.   if (!hMyNext && !hMyPrev)
  207.     return (FALSE);
  208.  
  209.   /* Update the prev pointer of the next block to point to
  210.    * the block previous to the one being deleted.
  211.    */
  212.  
  213.   if (hMyNext)
  214.     {
  215.       BlockPtr = (TypBlock far *) GlobalLock (hMyNext);
  216.       BlockPtr->hPrevBlock = hMyPrev;
  217.       GlobalUnlock (hMyNext);
  218.  
  219.       NextLine (CurBlockPtr, CurLinePtr);
  220.       set_cur_block = TRUE;
  221.     }
  222.   else
  223.     {
  224.       /* The block we are deleting has no next block, so it
  225.        * must be the last in the document.  Update document pointers.
  226.        */
  227.       MyBlockPtr->OwnerDoc->hLastBlock = hMyPrev;
  228.     }
  229.  
  230.   /* Update the next pointer of the previous block to point to
  231.    * the block after the one being deleted.
  232.    */
  233.  
  234.   if (hMyPrev)
  235.     {
  236.       BlockPtr = (TypBlock far *) GlobalLock (hMyPrev);
  237.       BlockPtr->hNextBlock = hMyNext;
  238.       GlobalUnlock (hMyPrev);
  239.  
  240.       if (!set_cur_block)
  241.    {
  242.      /* There is no next block, so we want to position the
  243.            * pointer to the end of the previous block.
  244.            */
  245.      PrevLine (CurBlockPtr, CurLinePtr);
  246.      NextLine (CurBlockPtr, CurLinePtr);
  247.    }
  248.     }
  249.   else
  250.     {
  251.       /* The block we are deleting has no previous block, so it
  252.        * must be the first in the document.  Update document pointers.
  253.        */
  254.       MyBlockPtr->OwnerDoc->hFirstBlock = hMyNext;
  255.     }
  256.  
  257.   GlobalFree (hMyBlock);
  258.   return (TRUE);
  259. }
  260.  
  261. /*-- function AddLine -------------------------------------------------
  262.  *
  263.  *  Add a line to a textblock.  Create a new textblock if necessary.
  264.  *
  265.  *    Entry    LineToAdd   points to a line to add.
  266.  *             CurBlockPtr points to the block to which we want to add it.
  267.  *             CurAddPtr   points to the place in the block to add the line.
  268.  *
  269.  *    Exit     CurBlockPtr & CurAddPtr point to right after the
  270.  *                newly-added line.
  271.  *
  272.  *    Method   There are three cases:
  273.  *             1. The new line will fit in the textblock.
  274.  *                That's pretty easy.
  275.  *             2. The new line won't fit, and we are at the end of
  276.  *                the current block.
  277.  *                I could have just treated this as I do case 3 (splitting
  278.  *                the textblock), but that would have resulted in
  279.  *                a lot of unnecessary internal fragmentation
  280.  *                (i.e., wasted space inside textblocks).
  281.  *                So, what I do is leave the contents of the old block
  282.  *                alone and just create a new empty block, to which
  283.  *                the line is added by a recursive call.
  284.  *             3. The new line won't fit, and we are not at the end of
  285.  *                the textblock.
  286.  *                In this case, I split the textblock at the first line
  287.  *                boundary after the split point (the split point is
  288.  *                an attribute of the document--usually about 2/3 of the
  289.  *                way through the textblock), creating two semi-full textblocks
  290.  *                where there was one full one before.
  291.  *                The routine then recursively calls itself.
  292.  */
  293. int
  294. AddLine (LineToAdd, CurBlockPtr, CurAddPtr)
  295.      TypLine *LineToAdd;
  296.      TypBlock far **CurBlockPtr;
  297.      TypLine far **CurAddPtr;
  298. {
  299.   TypBlock far *MyBlock = *CurBlockPtr;
  300.  
  301.   int left = (MyBlock->OwnerDoc->BlockSize - MyBlock->LWAp1);
  302.   
  303.   if (LineToAdd->length <= (int) left)
  304.     {
  305.  
  306.       /* There's room in the current block for this line, so just    */
  307.       /* move lines down to accomodate this line and copy it in.     */
  308.  
  309.       MoveBytes ((char far *) *CurAddPtr,
  310.        ((char far *) *CurAddPtr) + LineToAdd->length,
  311.        (((char far *) MyBlock + MyBlock->LWAp1)) - (char far *) *CurAddPtr);
  312.       MoveBytes ((char far *) LineToAdd, (char far *) *CurAddPtr,
  313.        LineToAdd->length);
  314.  
  315.       /* Adjust textblock counters.                                  */
  316.       MyBlock->LWAp1 += LineToAdd->length;
  317.       MyBlock->NumLines++;
  318.       if(LineToAdd->active) MyBlock->NumActiveLines++;
  319.       IncPtr ((*CurAddPtr), LineToAdd->length);
  320.       MyBlock->OwnerDoc->TotalLines++;
  321.     }
  322.   else
  323.     {
  324.  
  325.       /* There isn't enough room in the current textblock.           */
  326.       /* If we are at the end of the current block, just create      */
  327.       /* a new empty one; otherwise, split the current block.        */
  328.  
  329.       TypBlock far *NewBlockPtr;
  330.  
  331.       if ((*CurAddPtr)->length == END_OF_BLOCK)
  332.    {
  333.      /* We're at end of block; create a new empty one.           */
  334.      /* This will be the current block, so release references    */
  335.      /* to the now-current block                                 */
  336.      if (NewBlock (MyBlock, CurBlockPtr))
  337.        {
  338.          return (1);
  339.        }
  340.      else
  341.        {
  342.          GlobalUnlock (MyBlock->hCurBlock);
  343.          *CurAddPtr = (TypLine far *)
  344.       ((char far *) *CurBlockPtr + sizeof (TypBlock));
  345.          /* Now we can recursively try again to add the line.     */
  346.          if (AddLine (LineToAdd, CurBlockPtr, CurAddPtr))
  347.       {
  348.         return (1);
  349.       }
  350.        }
  351.    }
  352.       else
  353.    {
  354.      /* We need to split the textblock.                          */
  355.      /* Find a place to split the block by starting at the       */
  356.      /* beginning of the block and skipping through the lines    */
  357.      /* until we pass the number of bytes that marks the         */
  358.      /* split point.  The previous line is the split point.      */
  359.  
  360.      TypLine far *MyLinePtr = (TypLine far *) ((char far *) MyBlock + sizeof (TypBlock));
  361.      TypLine far *MyLastLine = MyLinePtr;
  362.      int nOldLines = 0, nBytesMoved, MyAddOffset;
  363.  
  364.      while ( (unsigned)((char far *) MyLinePtr - (char far *) MyBlock) <
  365.        MyBlock->OwnerDoc->SplitSize &&
  366.        MyLinePtr->length != END_OF_BLOCK)
  367.        {
  368.          nOldLines++;
  369.          MyLastLine = MyLinePtr;
  370.          IncPtr (MyLinePtr, MyLinePtr->length);
  371.        }
  372.  
  373.      /* Allocate the new block and copy the last portion of      */
  374.      /* the current block to the new one.   The range to         */
  375.      /* copy starts at the above-determined split point and      */
  376.      /* goes until the LWA+1.                                    */
  377.      /* Then adjust the new & old textblock fields.              */
  378.  
  379.      if (NewBlock (MyBlock, &NewBlockPtr))
  380.        {
  381.          return (1);
  382.        }
  383.      else
  384.        {
  385.          MoveBytes (MyLastLine, (char far *) NewBlockPtr + sizeof (TypBlock),
  386.           nBytesMoved = (((char far *) MyBlock + MyBlock->LWAp1)) - (char far *) MyLastLine);
  387.          MyBlock->LWAp1 = (char far *) MyLastLine - ((char far *) MyBlock)
  388.       + sizeof (TypLine);
  389.          ((TypLine far *) MyLastLine)->length = END_OF_BLOCK;
  390.          ((TypLine far *) MyLastLine)->LineID = NextLineID++;
  391.          NewBlockPtr->NumLines = MyBlock->NumLines - nOldLines;
  392.          MyBlock->NumLines = nOldLines;
  393.          NewBlockPtr->LWAp1 = nBytesMoved + sizeof (TypBlock);
  394.  
  395.          /* Should the new line go in the old block or the new?   */
  396.          /* If the add point is beyond the end of the newly-      */
  397.          /* truncated block, we must move the add point to the    */
  398.          /* next block and make the new block the current one.    */
  399.          /* The new position should be the same                   */
  400.          /* number of line bytes past the beginning of the next   */
  401.          /* block as it was past the split point when it was in   */
  402.          /* the old block.                                        */
  403.          /* Either way, one block (the old or the new one)        */
  404.          /* must be unlocked.                                     */
  405.  
  406.          if (*CurAddPtr >= MyLastLine)
  407.       {
  408.         /* Add point is in new block.                         */
  409.  
  410.         MyAddOffset = (char far *) *CurAddPtr - (char far *) MyLastLine + sizeof (TypBlock);
  411.         *CurAddPtr = (TypLine far *) ((char far *) NewBlockPtr + MyAddOffset);
  412.         *CurBlockPtr = NewBlockPtr;
  413.         GlobalUnlock (MyBlock->hCurBlock);
  414.       }
  415.          else
  416.       {
  417.         /* Add point is in current block.                     */
  418.         GlobalUnlock (NewBlockPtr->hCurBlock);
  419.       }
  420.          return (AddLine (LineToAdd, CurBlockPtr, CurAddPtr));
  421.        }
  422.    }
  423.     }
  424.   return (0);
  425. }
  426.  
  427. /*-- function ReplaceLine -------------------------------------------------
  428.  *
  429.  *  Replace a line in a textblock.  Create a new textblock if necessary.
  430.  *
  431.  *    Entry    LineToAdd   is the line to put into a textblock.
  432.  *             CurBlockPtr points to the block containing the old copy.
  433.  *             CurLinePtr  points to the old copy of the line.
  434.  *
  435.  *    Exit     returns TRUE if successful.
  436.  *             CurBlockPtr points to the block containing the new copy of the line.
  437.  *             CurLinePtr  points to the new copy of the line.
  438.  *                         Usually, CurBlockPtr & CurAddPtr will be the
  439.  *                         same upon exit as upon entry; however, sometimes
  440.  *                         a textblock split is necessary.
  441.  *
  442.  *    Method   There are two cases:
  443.  *             1. There is enough room in this textblock for the
  444.  *                changed line.
  445.  *                This is pretty simple.
  446.  *             2. There is not enough room in this textblock for the
  447.  *                changed line.  This requires a textblock split,
  448.  *                as with AddLine.  There's a lot of common code
  449.  *                here--should probably consolidate it in a single routine
  450.  *                some day.
  451.  */
  452. BOOL
  453. ReplaceLine (LineToAdd, CurBlockPtr, CurLinePtr)
  454.      TypLine *LineToAdd;
  455.      TypBlock far **CurBlockPtr;
  456.      TypLine far **CurLinePtr;
  457. {
  458.   TypBlock far *MyBlockPtr = *CurBlockPtr;
  459.   TypLine far *MyLinePtr = *CurLinePtr;
  460.   int deltasize;
  461.   int numbytes;
  462.   char far *target, far * source;
  463.  
  464.   deltasize = LineToAdd->length - (MyLinePtr->length);
  465.  
  466.   if (deltasize <= (int) (MyBlockPtr->OwnerDoc->BlockSize - MyBlockPtr->LWAp1))
  467.     {
  468.  
  469.       /* There's room in the current block for this line, so just    */
  470.       /* move lines down to accomodate this line and copy it in.     */
  471.       /* Move the data in the textblock up or down, starting with    */
  472.       /* the line after the line being replaced.                     */
  473.  
  474.       source = (char far *) MyLinePtr + MyLinePtr->length;
  475.       target = source + deltasize;
  476.       numbytes = ((char far *) MyBlockPtr + MyBlockPtr->LWAp1) -
  477.    (char far *) MyLinePtr - MyLinePtr->length;
  478.  
  479.       MoveBytes (source, target, numbytes);
  480.  
  481.       MoveBytes ((char far *) LineToAdd, (char far *) MyLinePtr,
  482.        LineToAdd->length);
  483.       MyBlockPtr->LWAp1 += deltasize;
  484.     }
  485.   else
  486.     {
  487.  
  488.       /* There isn't enough room in the current textblock.           */
  489.       /* We need to split the textblock.                          */
  490.       /* Find a place to split the block by starting at the       */
  491.       /* beginning of the block and skipping through the lines    */
  492.       /* until we pass the number of bytes that marks the         */
  493.       /* split point.  The previous line is the split point.      */
  494.  
  495.       TypBlock far *NewBlockPtr;
  496.  
  497.       TypLine far *MyLinePtr = (TypLine far *) ((char far *) MyBlockPtr + sizeof (TypBlock));
  498.       TypLine far *MyLastLine = MyLinePtr;
  499.       int nOldLines = 0, nBytesMoved, MyAddOffset;
  500.  
  501.       while ( (unsigned) ((char far *) MyLinePtr - (char far *) MyBlockPtr) <
  502.         MyBlockPtr->OwnerDoc->SplitSize &&
  503.         MyLinePtr->length != END_OF_BLOCK)
  504.    {
  505.      nOldLines++;
  506.      MyLastLine = MyLinePtr;
  507.      IncPtr (MyLinePtr, MyLinePtr->length);
  508.    }
  509.  
  510.       /* Allocate the new block and copy the last portion of      */
  511.       /* the current block to the new one.   The range to         */
  512.       /* copy starts at the above-determined split point and      */
  513.       /* goes until the LWA+1.                                    */
  514.       /* Then adjust the new & old textblock fields.              */
  515.  
  516.       if (NewBlock (MyBlockPtr, &NewBlockPtr))
  517.    {
  518.      return (1);
  519.    }
  520.       else
  521.    {
  522.      MoveBytes (MyLastLine, (char far *) NewBlockPtr + sizeof (TypBlock),
  523.            nBytesMoved = (((char far *) MyBlockPtr + MyBlockPtr->LWAp1)) - (char far *) MyLastLine);
  524.      MyBlockPtr->LWAp1 = (char far *) MyLastLine - ((char far *) MyBlockPtr)
  525.        + sizeof (TypLine);
  526.      ((TypLine far *) MyLastLine)->length = END_OF_BLOCK;
  527.      ((TypLine far *) MyLastLine)->LineID = NextLineID++;
  528.      NewBlockPtr->NumLines = MyBlockPtr->NumLines - nOldLines;
  529.      MyBlockPtr->NumLines = nOldLines;
  530.      NewBlockPtr->LWAp1 = nBytesMoved + sizeof (TypBlock);
  531.  
  532.      /* Should this line go in the old block or the new?   */
  533.      /* If the add point is beyond the end of the newly-      */
  534.      /* truncated block, we must move the add point to the    */
  535.      /* next block and make the new block the current one.    */
  536.      /* The new position should be the same                   */
  537.      /* number of line bytes past the beginning of the next   */
  538.      /* block as it was past the split point when it was in   */
  539.      /* the old block.                                        */
  540.      /* Either way, one block (the old or the new one)        */
  541.      /* must be unlocked.                                     */
  542.  
  543.      if (*CurLinePtr >= MyLastLine)
  544.        {
  545.          /* Replace point is in new block.                         */
  546.  
  547.          MyAddOffset = (char far *) *CurLinePtr - (char far *) MyLastLine + sizeof (TypBlock);
  548.          *CurLinePtr = (TypLine far *) ((char far *) NewBlockPtr + MyAddOffset);
  549.          *CurBlockPtr = NewBlockPtr;
  550.          GlobalUnlock (MyBlockPtr->hCurBlock);
  551.        }
  552.      else
  553.        {
  554.          /* Add point is in current block.                     */
  555.          GlobalUnlock (NewBlockPtr->hCurBlock);
  556.        }
  557.      return (ReplaceLine (LineToAdd, CurBlockPtr, CurLinePtr));
  558.    }
  559.     }
  560.   return (TRUE);
  561. }
  562.  
  563. /*-- function DeleteLine ----------------------------------------------
  564.  *
  565.  *  Delete a line from a textblock.
  566.  *
  567.  *    Entry    CurBlockPtr points to the block containing the line.
  568.  *             CurLinePtr  points to the line to delete.
  569.  *
  570.  *    Exit     returns TRUE if successful.
  571.  *             CurBlockPtr points to the block containing the next line,
  572.  *                         if any.
  573.  *             CurLinePtr  points to the next line, if any--else the
  574.  *                         end of the block.
  575.  *                         Usually, CurBlockPtr & CurLinePtr will be the
  576.  *                         same upon exit as upon entry; however, sometimes
  577.  *                         a textblock is emptied and the entire block
  578.  *                         is deleted.
  579.  */
  580. BOOL
  581. DeleteLine (TypBlock far ** CurBlockPtr, TypLine far ** CurLinePtr)
  582. {
  583.   TypBlock far *MyBlockPtr = *CurBlockPtr;
  584.   TypLine far *MyLinePtr = *CurLinePtr;
  585.   int bytes_to_end, bytes_to_copy;
  586.   int cur_length = MyLinePtr->length;
  587.  
  588.   /* If we are (erroneously) at the end of a block, do nothing */
  589.  
  590.   if (MyLinePtr->length == END_OF_BLOCK)
  591.     {
  592.       return (FALSE);
  593.     }
  594.  
  595.   /* Copy the remainder of the block on top of the line to be deleted. */
  596.  
  597.   bytes_to_end = ((char far *) MyBlockPtr + MyBlockPtr->LWAp1) -
  598.     (char far *) MyLinePtr;
  599.   bytes_to_copy = bytes_to_end - cur_length;
  600.   MoveBytes ((char far *) MyLinePtr + cur_length, (char far *) MyLinePtr,
  601.         bytes_to_copy);
  602.  
  603.   /* Update the block counters.  */
  604.  
  605.   MyBlockPtr->LWAp1 -= cur_length;
  606.   MyBlockPtr->NumLines--;
  607.   MyBlockPtr->OwnerDoc->TotalLines--;
  608.  
  609.   /* If we are now at the end of the block, we are faced with one of
  610.    * two situations:
  611.    * 1.  We are also at the beginning of the block, and hence
  612.    *     the block is empty.  In this case we must delete the block
  613.    *     unless it is the only block.
  614.    * 2.  Otherwise, we must advance to the next block, if any.
  615.    */
  616.  
  617.   if (MyLinePtr->length == END_OF_BLOCK)
  618.     {
  619.  
  620.       /* We are at the end of the block.  */
  621.  
  622.       if (*((int far *) (MyLinePtr) - 1) == END_OF_BLOCK)
  623.    {
  624.  
  625.      /* We have emptied the block.  We must check for whether
  626.            * this is the last block in the document.
  627.            */
  628.      if (MyBlockPtr->OwnerDoc->TotalLines)
  629.        {
  630.          /* The document is not empty.  Delete this empty block.
  631.                */
  632.          DeleteBlock (CurBlockPtr, CurLinePtr);
  633.        }
  634.      else
  635.        {
  636.          /* The document is empty.  Don't delete this block.
  637.                * Leave the pointer at the same place.  It is now pointing
  638.                * at the next line.
  639.                */
  640.        }
  641.    }
  642.       else
  643.    {
  644.      /* We're at the end of the block, but the block is not empty.
  645.            * Just advance to the next block, if any.
  646.            */
  647.      NextLine (CurBlockPtr, CurLinePtr);
  648.    }
  649.     }
  650.  
  651.   return (TRUE);
  652. }
  653.  
  654.  
  655. /*-- function NextLine ------------------------------------------------
  656.  *
  657.  *  Advance a pointer to point to the next line in a document.
  658.  *
  659.  *    Entry    BlockPtr    points to the current block.
  660.  *             LinePtr     points to the current line.
  661.  *
  662.  *    Exit     BlockPtr & LinePtr point to the next line, if there
  663.  *              was one.
  664.  *             Returns TRUE iff pointer was moved.
  665.  *
  666.  *    Method   Must advance BlockPtr if LinePtr was at the end
  667.  *             of a block to start with, or arrives at the end of a block
  668.  *             after moving to the end of the current line.
  669.  */
  670. int
  671. NextLine (BlockPtr, LinePtr)
  672.      TypBlock far **BlockPtr;
  673.      TypLine far **LinePtr;
  674. {
  675.   BOOL retcode = 0;
  676.  
  677.   if ((*LinePtr)->length != END_OF_BLOCK)
  678.     {
  679. /*      (char far *) *LinePtr += (*LinePtr)->length; */
  680.       IncPtr (*LinePtr, (*LinePtr)->length);
  681.     }
  682.   if ((*LinePtr)->length == END_OF_BLOCK)
  683.     {
  684.       if ((*BlockPtr)->hNextBlock)
  685.    {
  686.      GlobalUnlock ((*BlockPtr)->hCurBlock);
  687.      *BlockPtr = (TypBlock far *) GlobalLock ((*BlockPtr)->hNextBlock);
  688.      *LinePtr = (TypLine far *) ((char far *) *BlockPtr + sizeof (TypBlock));
  689.      retcode = 1;
  690.    }
  691.     }
  692.   else
  693.     {
  694.       retcode = 1;
  695.     }
  696.   return (retcode);
  697. }
  698.  
  699. /*-- function PrevLine ------------------------------------------------
  700.  *
  701.  *  Back up a pointer to point to the next line in a document.
  702.  *
  703.  *    Entry    BlockPtr    points to the current block.
  704.  *             LinePtr     points to the current line.
  705.  *
  706.  *    Exit     BlockPtr & LinePtr point to the previous line, if there
  707.  *              was one.
  708.  *             Returns TRUE iff pointer was moved.
  709.  *
  710.  *    Method   Rely on the fact that the last field of the previous
  711.  *             line is the length of that line.  Also, the last field
  712.  *             in a textblock header (which is what you get if you
  713.  *             try to look at the previous line in a textblock if you're
  714.  *             at the beginning of a textblock) has the value END_OF_BLOCK.
  715.  */
  716. int
  717. PrevLine (BlockPtr, LinePtr)
  718.      TypBlock far **BlockPtr;
  719.      TypLine far **LinePtr;
  720. {
  721.   if (*((int far *) (*LinePtr) - 1) != END_OF_BLOCK)
  722.     {
  723. /*      (char far *) *LinePtr -= *((int far *)(*LinePtr)-1); */
  724.       IncPtr (*LinePtr, -(*((int far *) (*LinePtr) - 1)));
  725.     }
  726.   else
  727.     {
  728.       if ((*BlockPtr)->hPrevBlock)
  729.    {
  730.      GlobalUnlock ((*BlockPtr)->hCurBlock);
  731.      *BlockPtr = (TypBlock far *) GlobalLock ((*BlockPtr)->hPrevBlock);
  732.      *LinePtr = (TypLine far *)
  733.        ((char far *) *BlockPtr + (*BlockPtr)->LWAp1 - sizeof (TypLine));
  734. /*         (char far *) *LinePtr -= ( *((int far *)(*LinePtr)-1)); */
  735.      IncPtr (*LinePtr, -(*((int far *) (*LinePtr) - 1)));
  736.    }
  737.       else
  738.    {
  739.      return (0);
  740.    }
  741.     }
  742.   return (1);
  743. }
  744.  
  745. /*--- function TopOfDoc ------------------------------------------------
  746.  *
  747.  *   Set pointers to the first line of a document.
  748.  *
  749.  *    Entry    Doc         points to a document.
  750.  *
  751.  *    Exit     BlockPtr, LinePtr   point to the first
  752.  *                         line in the document.  This line is locked.
  753.  */
  754. void
  755. TopOfDoc (Doc, BlockPtr, LinePtr)
  756.      TypDoc *Doc;
  757.      TypBlock far **BlockPtr;
  758.      TypLine far **LinePtr;
  759. {
  760.   HANDLE hBlock;
  761.   int Offset;
  762.   TypLineID MyLineID;
  763.  
  764.   hBlock = Doc->hFirstBlock;
  765.   Offset = sizeof (TypBlock);
  766.   MyLineID = 0L;
  767.   LockLine (hBlock, Offset, MyLineID, BlockPtr, LinePtr);
  768. }
  769.  
  770. /*--- function ExtractTextLine -----------------------------------------------
  771.  *
  772.  *  Extract the text portion of a line to another buffer.
  773.  *
  774.  *    Entry    Doc      points to the document.
  775.  *             LinePtr  points to a line.
  776.  *             BufSize  is the size of the output buffer in bytes.
  777.  *
  778.  *    Exit     Buf      contains the text, terminated by a zero byte.
  779.  *             Returns FALSE iff no text could be extracted
  780.  *               (not a valid line).
  781.  */
  782. BOOL
  783. ExtractTextLine (Doc, LinePtr, Buf, BufSize)
  784.      TypDoc *Doc;
  785.      TypLine far *LinePtr;
  786.      char *Buf;
  787.      int BufSize;
  788. {
  789.   char far *bptr;
  790.   BOOL DidIt = FALSE;
  791.  
  792.   if (LinePtr->length == END_OF_BLOCK)
  793.     {
  794.     }
  795.   else
  796.     {
  797.       if (Doc->DocType == DOCTYPE_NET)
  798.    {
  799.      bptr = (char far *) LinePtr + sizeof (TypLine) + sizeof (TypGroup);
  800.      while (--BufSize > 1 && (*(Buf++) = *(bptr++)));
  801.      *Buf = '\0';
  802.      DidIt = TRUE;
  803.    }
  804.       else if (Doc->DocType == DOCTYPE_ARTICLE)
  805.    {
  806.      bptr = (char far *) LinePtr + sizeof (TypLine) + sizeof (TypText);
  807.      while (--BufSize > 1 && (*(Buf++) = *(bptr++)));
  808.      *Buf = '\0';
  809.      DidIt = TRUE;
  810.    }
  811.     }
  812.   return (DidIt);
  813. }
  814.  
  815. /*-- function LockLine ---------------------------------------------
  816.  *
  817.  *  Find the specified line, and return a pointer to it.
  818.  *  Lock the line in memory.
  819.  *
  820.  *  Entry:  hBlock      is the handle of a block we think contains
  821.  *                      the desired line.
  822.  *          LineOff     is the offset in bytes from the beginning of
  823.  *                      the block for where we think the line is.
  824.  *          FindLineID  is the LineID of the desired line.
  825.  *                      If it is 0, we don't check line ID's (don't care).
  826.  *
  827.  *  Exit:   returns     TRUE iff the line was found.
  828.  *          BlockPtr    points to the beginning of the block
  829.  *                      in which the line was found.
  830.  *          LinePtr     points to the line.
  831.  */
  832. BOOL
  833. LockLine (hBlock, LineOff, FindLineID, BlockPtr, LinePtr)
  834.      HANDLE hBlock;
  835.      unsigned int LineOff;
  836.      TypLineID FindLineID;
  837.      TypBlock far **BlockPtr;
  838.      TypLine far **LinePtr;
  839. {
  840.   *BlockPtr = (TypBlock far *) GlobalLock (hBlock);
  841.   *LinePtr = (TypLine far *) ((char far *) *BlockPtr + LineOff);
  842.   if (FindLineID && (*LinePtr)->LineID != FindLineID)
  843.     {
  844.       /* The location specified by hBlock and LineOff does not
  845.        * contain the right line.  So, unlock that block and start
  846.        * scanning the document from the top, looking for the line.
  847.        */
  848.       TypBlock far *MyBlockPtr;
  849.       TypLine far *MyLinePtr;
  850.       HANDLE hMyBlock;
  851.       int MyOffset;
  852.  
  853.       hMyBlock = (*BlockPtr)->OwnerDoc->hFirstBlock;
  854.       MyOffset = sizeof (TypBlock);
  855.       GlobalUnlock (hBlock);
  856.  
  857.       MyBlockPtr = (TypBlock far *) GlobalLock (hMyBlock);
  858.       MyLinePtr = (TypLine far *) ((char far *) MyBlockPtr + sizeof (TypBlock));
  859.  
  860.       while (MyLinePtr->LineID != FindLineID && NextLine (&MyBlockPtr, &MyLinePtr));
  861.  
  862.       if (MyLinePtr->LineID == FindLineID)
  863.    {
  864.      *BlockPtr = MyBlockPtr;
  865.      *LinePtr = MyLinePtr;
  866.    }
  867.       else
  868.    {
  869.      MessageBox (hWndConf, "Can't find line", "in LockLine", MB_ICONHAND | MB_OK);
  870.      return (FALSE);
  871.    }
  872.     }
  873.   return (TRUE);
  874. }
  875.  
  876. /*-- function UnlockLine ---------------------------------------------
  877.  *
  878.  *  Given a block pointer and a line pointer, unlock the block
  879.  *  in memory and return a line ID, a block handle and an offset within the
  880.  *  block to the line.
  881.  *
  882.  *    Entry    BlockPtr    points to a textblock
  883.  *             LinePtr     points to a line in that textblock
  884.  *
  885.  *    Exit     TheLineID   is the LineID of the pointed-to line.
  886.  *             hBlock      is the handle to the textblock.
  887.  *             LineOff     is the offset (in bytes from the beginning
  888.  *                         of the block) of the line.
  889.  */
  890. void
  891. UnlockLine (BlockPtr, LinePtr, hBlock, LineOff, TheLineID)
  892.      TypBlock far *BlockPtr;
  893.      TypLine far *LinePtr;
  894.      HANDLE *hBlock;
  895.      unsigned int *LineOff;
  896.      TypLineID *TheLineID;
  897. {
  898.   PtrToOffset (BlockPtr, LinePtr, hBlock, LineOff, TheLineID);
  899.   GlobalUnlock (*hBlock);
  900. }
  901.  
  902. /*-- function PtrToOffset ---------------------------------------------
  903.  *
  904.  *  Given a block pointer and a line pointer,
  905.  *  return a line ID, a block handle and an offset within the
  906.  *  block to the line.
  907.  *
  908.  *    Entry    BlockPtr    points to a textblock
  909.  *             LinePtr     points to a line in that textblock
  910.  *
  911.  *    Exit     TheLineID   is the LineID of the pointed-to line.
  912.  *             hBlock      is the handle to the textblock.
  913.  *             LineOff     is the offset (in bytes from the beginning
  914.  *                         of the block) of the line.
  915.  */
  916. void
  917. PtrToOffset (BlockPtr, LinePtr, hBlock, LineOff, TheLineID)
  918.      TypBlock far *BlockPtr;
  919.      TypLine far *LinePtr;
  920.      HANDLE *hBlock;
  921.      unsigned int *LineOff;
  922.      TypLineID *TheLineID;
  923. {
  924.   *TheLineID = LinePtr->LineID;
  925.   *LineOff = (char far *) LinePtr - (char far *) BlockPtr;
  926.   *hBlock = BlockPtr->hCurBlock;
  927. }
  928.  
  929. /*-- function WhatLine ------------------------------------------------
  930.  *
  931.  *  Determine the ordinal number of a given line in the document.
  932.  *
  933.  *    Entry    BlockPtr    points to the block containing a line.
  934.  *             LinePtr     points to the line.
  935.  *
  936.  *    Exit     Returns 0 = first line, 1 = second, and so on.
  937.  *
  938.  *  Strategy is to start at the beginning of the document and
  939.  *  scan though the lines, counting lines until we reach the
  940.  *  current line.  In more detail:
  941.  *
  942.  *  Save the current position.
  943.  *  Go to the first block of the document.
  944.  *  Number of lines = 0
  945.  *  While we are not yet at the original block,
  946.  *     Add in the number of lines in this block, just by looking at header.
  947.  *  Now that we have reached the original block, start at the
  948.  *     beginning of the block and scan forward line-by-line until
  949.  *     we reach the original line.
  950.  */
  951. unsigned int
  952. WhatLine (BlockPtr, LinePtr)
  953.      TypBlock far *BlockPtr;
  954.      TypLine far *LinePtr;
  955. {     
  956. #if 0
  957.    /* This older code is faster, but ignores the distinction 
  958.     * between active and inactive lines.  /mrr
  959.     */
  960.   unsigned int nLines = 0;
  961.   TypBlock far *MyBlock;
  962.   TypLine far *MyLine;
  963.   TypDoc *MyDoc;
  964.   HANDLE hOrgBlock, hMyBlock, hNewBlock;
  965.   unsigned int OrgOffset, MyOffset;
  966.   TypLineID OrgLineID, MyLineID = 0L;
  967.  
  968.   MyDoc = BlockPtr->OwnerDoc;
  969.   UnlockLine (BlockPtr, LinePtr, &hOrgBlock, &OrgOffset, &OrgLineID);
  970.  
  971.   hMyBlock = MyDoc->hFirstBlock;
  972.   while (hMyBlock != hOrgBlock)
  973.     {
  974.       MyBlock = (TypBlock far *) GlobalLock (hMyBlock);
  975.       nLines += MyBlock->NumLines;
  976.       hNewBlock = MyBlock->hNextBlock;
  977.       if (!hNewBlock)
  978.    {
  979.      MessageBox (MyDoc->hDocWnd, "Hit end of document", "Error in WhatLine",
  980.             MB_OK | MB_ICONHAND);
  981.    }
  982.       GlobalUnlock (hMyBlock);
  983.       hMyBlock = hNewBlock;
  984.     }
  985.  
  986.   /* The technique of scanning the NumLines field starts the        */
  987.   /* counter at 1 rather than 0, so if we got any lines above,      */
  988.   /* adjust the count by decrementing it.                           */
  989.  
  990. /* if(nLines) nLines--; */
  991.  
  992.   /* We have reached the original block.                            */
  993.   /* Start scanning at the first line.                              */
  994.  
  995.   MyOffset = sizeof (TypBlock);
  996.   LockLine (hMyBlock, MyOffset, MyLineID, &MyBlock, &MyLine);
  997.   while (MyOffset != OrgOffset)
  998.     {
  999.       nLines++;
  1000.       NextLine (&MyBlock, &MyLine);
  1001.       MyOffset = (char far *) MyLine - (char far *) MyBlock;
  1002.     }
  1003. #else
  1004.   unsigned int nLines = 0;
  1005.   TypBlock far *MyBlock;
  1006.   TypLine far *MyLine;
  1007.   TypDoc *MyDoc;
  1008.             
  1009.    MyDoc = BlockPtr->OwnerDoc;
  1010.    TopOfDoc(MyDoc,&MyBlock,&MyLine);
  1011.    while(MyLine != LinePtr) {
  1012.       if(MyLine->active) nLines++;
  1013.       if(!NextLine(&MyBlock,&MyLine)) {
  1014.          MessageBox (MyDoc->hDocWnd, "Hit end of document", "Error in WhatLine",
  1015.             MB_OK | MB_ICONHAND);
  1016.       }
  1017.    }
  1018. #endif
  1019.   return (nLines);
  1020. }
  1021.  
  1022. /*--- function NumBlocksInDoc --------------------------------------------
  1023.  *
  1024.  *  Find the number of blocks in a document.
  1025.  *
  1026.  * Entry Doc points to a document.
  1027.  *
  1028.  * Exit  returns the number of textblocks in the document.
  1029.  */
  1030. int
  1031. NumBlocksInDoc (Doc)
  1032.      TypDoc *Doc;
  1033. {
  1034.   TypBlock far *MyBlock;
  1035.   HANDLE hMyBlock, hNewBlock;
  1036.   int nBlocks = 0;
  1037.  
  1038.   if (!Doc)
  1039.     return (0);
  1040.   hMyBlock = Doc->hFirstBlock;
  1041.   do
  1042.     {
  1043.       nBlocks++;
  1044.       MyBlock = (TypBlock far *) GlobalLock (hMyBlock);
  1045.       hNewBlock = MyBlock->hNextBlock;
  1046.       GlobalUnlock (hMyBlock);
  1047.       hMyBlock = hNewBlock;
  1048.     }
  1049.   while (hNewBlock);
  1050.  
  1051.   return (nBlocks);
  1052. }
  1053.  
  1054. /*--- function FindLineOrd ---------------------------------------------
  1055.  *
  1056.  *  Find the Nth line in a document.
  1057.  *
  1058.  *    Entry    Doc      points to a document.
  1059.  *             LineOrd  is the ordinal of the line to find.
  1060.  *                      0 = first line in document.
  1061.  *
  1062.  *    Exit     BlockPtr points to the block containing the line.
  1063.  *             LinePtr  points to the line.
  1064.  *             return value is TRUE iff we found the line.
  1065.  */
  1066. BOOL
  1067. FindLineOrd (Doc, LineOrd, BlockPtr, LinePtr)
  1068.      TypDoc *Doc;
  1069.      unsigned int LineOrd;
  1070.      TypBlock far **BlockPtr;
  1071.      TypLine far **LinePtr;
  1072. {
  1073. #if 1
  1074.    /* This old code is faster, but ignores the distinction between
  1075.     * active and inactive lines.   /mrr
  1076.     */
  1077.   unsigned int LinesSoFar = 0;
  1078.   TypBlock far *MyBlockPtr;
  1079.   TypLine far *MyLinePtr;
  1080.   HANDLE hBlock, hNextBlock;
  1081.   int retcode = 0;
  1082.  
  1083.   hBlock = Doc->hFirstBlock;
  1084.   do
  1085.     {
  1086.       MyBlockPtr = (TypBlock far *) GlobalLock (hBlock);
  1087.       if (LinesSoFar + MyBlockPtr->NumActiveLines > LineOrd)
  1088.    break;
  1089.       LinesSoFar += MyBlockPtr->NumActiveLines;
  1090.       hNextBlock = MyBlockPtr->hNextBlock;
  1091.       GlobalUnlock (hBlock);
  1092.       hBlock = hNextBlock;
  1093.     }
  1094.   while (hBlock);
  1095.  
  1096.   if (hBlock)
  1097.     {
  1098.       MyLinePtr = (TypLine far *) ((char far *) MyBlockPtr + sizeof (TypBlock));
  1099.       AdvanceToActive(&MyBlockPtr,&MyLinePtr);
  1100.       while (LinesSoFar < LineOrd)
  1101.    {
  1102.      if (!NextLine (&MyBlockPtr, &MyLinePtr))
  1103.        break;
  1104.      if(MyLinePtr->active)LinesSoFar++;
  1105.    }
  1106.       retcode = TRUE;
  1107.       *BlockPtr = MyBlockPtr;
  1108.       *LinePtr = MyLinePtr;
  1109.     }
  1110. #else
  1111.   TypBlock far *MyBlockPtr;
  1112.   TypLine far *MyLinePtr;
  1113.   HANDLE hMyBlock;
  1114.   unsigned int MyOffset;
  1115.   TypLineID MyLineID;
  1116.   int retcode = FALSE;
  1117.   
  1118.   TopOfDoc(Doc,BlockPtr,LinePtr);
  1119.   while(1) {
  1120.       if((*LinePtr)->active) {
  1121.          if(!LineOrd--) {
  1122.             retcode = TRUE;
  1123.             break;
  1124.          } 
  1125.       }
  1126.       if(!NextLine(BlockPtr,LinePtr)) {
  1127.          break;
  1128.       }
  1129.   }            
  1130.   /*UnlockLine(BlockPtr,LinePtr,&hMyBlock,&MyOffset,&MyLineID); */
  1131. #endif
  1132.   return (retcode);
  1133. }
  1134.  
  1135. /*-- function MoveBytes -----------------------------------------------
  1136.  *
  1137.  *   Move a region of bytes in memory from one place to another.
  1138.  *   Handle overlapping regions without destroying the source.
  1139.  *
  1140.  *    Entry    Source   points to the FWA of the source.
  1141.  *             Target   points to the FWA of the target.
  1142.  *             NumBytes is the number of bytes to copy (>= 0).
  1143.  */
  1144. void
  1145. MoveBytes (FSource, FTarget, NumBytes)
  1146.      void far *FSource, far * FTarget;
  1147.      int NumBytes;
  1148. {
  1149.   char huge *Source = FSource;
  1150.   char huge *Target = FTarget;
  1151.  
  1152.   if (Source < Target)
  1153.     {
  1154.       Source += NumBytes - 1;
  1155.       Target += NumBytes - 1;
  1156.       while (NumBytes--)
  1157.    *(Target--) = *(Source--);
  1158.     }
  1159.   else
  1160.     {
  1161.       while (NumBytes--)
  1162.    *(Target++) = *(Source++);
  1163.     }
  1164. }
  1165.  
  1166. /*--- function InitDoc ---------------------------------------------------
  1167.  *
  1168.  *  Initialize the fields of a document.
  1169.  */
  1170. int
  1171. InitDoc (Doc, hWnd, Parent, DType)
  1172.      TypDoc *Doc;
  1173.      HWND hWnd;
  1174.      TypDoc *Parent;
  1175.      int DType;
  1176. {
  1177.   TypBlock far *BlockPtr;
  1178.   HANDLE hBlock;
  1179.  
  1180.   Doc->hLastBlock = 0;
  1181.   Doc->TotalLines = 0;
  1182.   Doc->HeaderLines = 0;
  1183.   Doc->ActiveLines = 0;
  1184.   Doc->BlockSize = BLOCK_SIZE;
  1185.   Doc->SplitSize = (BLOCK_SIZE * 2) / 3;
  1186.   Doc->hDocWnd = hWnd;
  1187.   Doc->hLastSeenBlock = 0;
  1188.   Doc->TopLineOrd = 0;
  1189.   Doc->ParentDoc = Parent;
  1190.   Doc->ParentLineID = 0L;
  1191.   Doc->SearchStr[0] = '\0';
  1192.   Doc->FindLineID = 0L;
  1193.   Doc->TopScLineID = 0L;
  1194.   Doc->InUse = TRUE;
  1195.   Doc->DocType = DType;
  1196.   Doc->hFindBlock = 0;
  1197.  
  1198.   switch (DType)
  1199.     {
  1200.     case DOCTYPE_NET:
  1201.       Doc->OffsetToText = sizeof (TypLine) + sizeof (TypGroup);
  1202.       break;
  1203.     case DOCTYPE_GROUP:
  1204.       Doc->OffsetToText = sizeof (TypLine) + sizeof (TypArticle);
  1205.       break;
  1206.     case DOCTYPE_ARTICLE:
  1207.       Doc->OffsetToText = sizeof (TypLine) + sizeof (TypText);
  1208.       break;
  1209.     }
  1210.  
  1211.   hBlock = GlobalAlloc (GMEM_MOVEABLE, (long) BLOCK_SIZE);
  1212.   if (hBlock)
  1213.     {
  1214.       BlockPtr = (TypBlock far *) GlobalLock (hBlock);
  1215.       SetupEmptyBlock (BlockPtr, hBlock, 0, 0, Doc);
  1216.  
  1217.       Doc->hFirstBlock = hBlock;
  1218.       Doc->hLastBlock = hBlock;
  1219.       Doc->hCurAddBlock = hBlock;
  1220.       Doc->AddOffset = sizeof (TypBlock);
  1221.       Doc->AddLineID = 0L;
  1222.       Doc->hCurTopScBlock = hBlock;
  1223.       Doc->TopScOffset = sizeof (TypBlock);
  1224.       Doc->TopScLineID = 0L;
  1225.       Doc->LastSeenLineID = 0L;
  1226.  
  1227.       GlobalUnlock (hBlock);
  1228.     }
  1229.   else
  1230.     {
  1231.       MessageBox (hWnd, "Could not allocate textblock", "Out of Memory Error", MB_OK | MB_ICONHAND);
  1232.     }
  1233.  
  1234.   return (0);
  1235. }
  1236.  
  1237. /*-- function FreeDoc ----------------------------------------------
  1238.  *
  1239.  *  Free up all the text blocks associated with a document.
  1240.  *
  1241.  *    Entry    Doc   points to the document in question.
  1242.  */
  1243. void
  1244. FreeDoc (Doc)
  1245.      TypDoc *Doc;
  1246. {
  1247.   TypBlock far *BlockPtr;
  1248.   HANDLE hBlock, hNextBlock;
  1249.  
  1250.   /* Start at the first block of the document, and travel           */
  1251.   /* down the linked list of blocks, freeing them.                  */
  1252.  
  1253.   hBlock = Doc->hFirstBlock;
  1254.   while (hBlock)
  1255.     {
  1256.       BlockPtr = (TypBlock far *) GlobalLock (hBlock);
  1257.       hNextBlock = BlockPtr->hNextBlock;
  1258.       GlobalUnlock (hBlock);
  1259.       GlobalFree (hBlock);
  1260.       hBlock = hNextBlock;
  1261.     }
  1262. }
  1263.  
  1264. /*--- function ForAllLines ---------------------------------------------
  1265.  *
  1266.  *  Perform an operation for all lines in a document.  The operation
  1267.  *  to be performed is specified by a C function argument.
  1268.  *
  1269.  *    Entry Doc            is the document.
  1270.  *          lpfnFunc       is a pointer to the function to call for
  1271.  *                         each line.
  1272.  *          lFlag          is a flag that's passed to the function.
  1273.  *
  1274.  */
  1275. void
  1276. ForAllLines (TypDoc *Doc, 
  1277.        void lpfnFunc(TypDoc *Doc, TypBlock far ** BlockPtr, TypLine far ** LinePtr, int wFlag, int wValue),
  1278.        int wFlag, int wValue)
  1279. {
  1280.   TypBlock far *BlockPtr;
  1281.   TypLine far *LinePtr;
  1282.   TypLineID old_lineID;
  1283.   BOOL looping = TRUE;
  1284.  
  1285.  
  1286.   TopOfDoc (Doc, &BlockPtr, &LinePtr);
  1287.   if (LinePtr->length != END_OF_BLOCK)
  1288.     {
  1289.       do
  1290.    {
  1291.      old_lineID = LinePtr->LineID;
  1292.      lpfnFunc (Doc, &BlockPtr, &LinePtr, wFlag, wValue);
  1293.      if (old_lineID == LinePtr->LineID &&
  1294.          LinePtr->length != END_OF_BLOCK)
  1295.        {
  1296.          looping = NextLine (&BlockPtr, &LinePtr);
  1297.        }
  1298.      else if (LinePtr->length == END_OF_BLOCK)
  1299.        {
  1300.          looping = FALSE;
  1301.        }
  1302.    }
  1303.       while (looping);
  1304.     }
  1305. /*   UnlockLine (BlockPtr, LinePtr,
  1306.     &(FindDoc->hFindBlock), &(FindDoc->FindOffset), &(FindDoc->FindLineID)); */
  1307.  
  1308. }
  1309.  
  1310. /*--- function ForAllBlocks ---------------------------------------------
  1311.  *
  1312.  *  Perform an operation for all blocks in a document.  The operation
  1313.  *  to be performed is specified by a C function argument.
  1314.  *
  1315.  *    Entry Doc            is the document.
  1316.  *          lpfnFunc       is a pointer to the function to call for
  1317.  *                         each block.
  1318.  *          lFlag          is a flag that's passed to the function.
  1319.  *
  1320.  */
  1321. void
  1322. ForAllBlocks (TypDoc *Doc, 
  1323.        void lpfnFunc(TypDoc *Doc, TypBlock far ** BlockPtr, int wFlag, int wValue),
  1324.        int wFlag, int wValue)
  1325. {
  1326.   TypBlock far *BlockPtr; 
  1327.   HANDLE hMyBlock, hNewBlock;
  1328.  
  1329.   if (!Doc)
  1330.     return ;
  1331.     
  1332.   hMyBlock = Doc->hFirstBlock;
  1333.   do
  1334.     {
  1335.       BlockPtr = (TypBlock far *) GlobalLock (hMyBlock);
  1336.       lpfnFunc(Doc,&BlockPtr,wFlag,wValue);
  1337.       hNewBlock = BlockPtr->hNextBlock;
  1338.       GlobalUnlock (hMyBlock);
  1339.       hMyBlock = hNewBlock;
  1340.     }
  1341.   while (hNewBlock);
  1342.  
  1343. }
  1344.  
  1345. /*--- function SetForBlock -----------------------------------
  1346.  *
  1347.  *  Perform a function for a block.
  1348.  *  This is called by ForAllBlocks.
  1349.  *
  1350.  *  Entry:  Doc      points to a document
  1351.  *          BlockPtr points to a block
  1352.  *          wFlag    is a general-purpose flag. 
  1353.  *          wValue   is a general-purpose value.
  1354.  */
  1355. void
  1356. SetForBlock(TypDoc *Doc, TypBlock far ** BlockPtr, int wFlag, int wValue)
  1357. {
  1358.    switch (wFlag) {
  1359.       case BLOCK_ACTION_SET_ACTIVE:
  1360.          (*BlockPtr)->NumActiveLines = wValue;
  1361.          break;
  1362.    }
  1363. }
  1364.  
  1365.  
  1366. /*--- function FindString ----------------------------------------------
  1367.  *
  1368.  *   Locate a search string in a document.
  1369.  *
  1370.  *   Entry  StartAtTop        is TRUE iff we should start the search at
  1371.  *                            the top of the document.
  1372.  *          FindDoc           points to the document in which we are searching.
  1373.  *          ->hFindBlock      is the block to start at, if StartAtTop
  1374.  *                            is FALSE.
  1375.  *          ->FindOffset      is the offset within the block of the
  1376.  *                            line to start at, if StartAtTop is FALSE.
  1377.  *          ->SearchStr       has the string to search for.
  1378.  *
  1379.  *   Exit   returns -1 if the string was not found,
  1380.  *            else the offset of the string from the beginning of the line.
  1381.  *          FindDoc ...
  1382.  *          ->hFindBlock      has the block handle of the line which
  1383.  *                            was found (if any)
  1384.  *          ->FindOffset      has the offset of the found line (if any)
  1385.  *
  1386.  */
  1387. int
  1388. FindString (StartAtTop)
  1389.      BOOL StartAtTop;
  1390. {
  1391.   TypBlock far *BlockPtr;
  1392.   TypLine far *LinePtr;
  1393.   HANDLE hBlock;
  1394.   unsigned int Offset;
  1395.   unsigned int TextOffset;
  1396.   BOOL found = -1;
  1397.   int TargLen = 0;
  1398.   int SourceLen;
  1399.   char *Target;
  1400.   char sourceline[MAXINTERNALLINE];
  1401.   char targline[MAXFINDSTRING];
  1402.   char *sourceptr, far * orglineptr;
  1403.   char *targptr;
  1404.   TypLineID MyLineID;
  1405.   register char ch;
  1406.  
  1407.   if (StartAtTop)
  1408.     {
  1409.       hBlock = FindDoc->hFirstBlock;
  1410.       Offset = sizeof (TypBlock);
  1411.       MyLineID = 0L;
  1412.     }
  1413.   else
  1414.     {
  1415.       hBlock = FindDoc->hFindBlock;
  1416.       Offset = FindDoc->FindOffset;
  1417.       MyLineID = FindDoc->FindLineID;
  1418.     }
  1419.   LockLine (hBlock, Offset, MyLineID, &BlockPtr, &LinePtr);
  1420.   /* If doing a Find Next, skip forward one line before starting    */
  1421.   /* the search.                                                    */
  1422.   if (!StartAtTop)
  1423.     {
  1424.       NextLine (&BlockPtr, &LinePtr);
  1425.     }
  1426.  
  1427.   TextOffset = FindDoc->OffsetToText;
  1428.  
  1429.   Target = FindDoc->SearchStr;
  1430.   for (targptr = targline; ch = *Target, *(targptr++) = tolower (ch);
  1431.        TargLen++)
  1432.     Target++;
  1433.  
  1434.   if (LinePtr->length != END_OF_BLOCK)
  1435.     {
  1436.       do
  1437.    { 
  1438.     if(LinePtr->active) {
  1439.      orglineptr = (char far *) LinePtr + TextOffset;
  1440.      sourceptr = sourceline;
  1441.      for (SourceLen = 0; ch = *(orglineptr),
  1442.           *(sourceptr++) = tolower (ch); SourceLen++)
  1443.        orglineptr++;
  1444.      found = SearchLine (sourceline, SourceLen, targline, TargLen);
  1445.     }
  1446.    }
  1447.       while (found == -1 && NextLine (&BlockPtr, &LinePtr));
  1448.     }
  1449.   UnlockLine (BlockPtr, LinePtr,
  1450.     &(FindDoc->hFindBlock), &(FindDoc->FindOffset), &(FindDoc->FindLineID));
  1451.   return (found);
  1452. }
  1453.  
  1454. /*--- function SearchLine -----------------------------------------------
  1455.  *
  1456.  *  Search a line for a target string.
  1457.  *
  1458.  *  Entry   Line     is a zero-terminated string to search.
  1459.  *          LineLen  is strlen(Line).  Redundant, but passed for
  1460.  *                   efficiency.
  1461.  *          Target   is the Target string to search for, zero-terminated.
  1462.  *          TargLen  is strlen(Target), passed for efficiency.
  1463.  *
  1464.  *  Exit    returns  -1 if not found, else the character position
  1465.  *                   in which the string was found (0=first).
  1466.  */
  1467. int
  1468. SearchLine (Line, LineLen, Target, TargLen)
  1469.      char *Line;
  1470.      int LineLen;
  1471.      char *Target;
  1472.      int TargLen;
  1473. {
  1474.   char *stopptr = Line + LineLen - TargLen + 1;
  1475.   char *lineptr;
  1476.   char *searchptr;
  1477.   char *targptr;
  1478.  
  1479.   if (LineLen <= 0 || TargLen <= 0 || TargLen > LineLen)
  1480.     return (-1);
  1481.  
  1482.   for (lineptr = Line; lineptr != stopptr; lineptr++)
  1483.     {
  1484.       searchptr = lineptr;
  1485.       for (targptr = Target; *targptr && *(targptr) == *(searchptr);)
  1486.    {
  1487.      targptr++;
  1488.      searchptr++;
  1489.    }
  1490.       if (!(*targptr))
  1491.    {
  1492.      return (lineptr - Line);
  1493.    }
  1494.     }
  1495.   return (-1);
  1496. }
  1497.  
  1498. /*--- function DoFind ---------------------------------------------------
  1499.  *
  1500.  *  Controlling routine for searching for text.
  1501.  *  Takes care of displaying window properly when search is done.
  1502.  *
  1503.  *    Entry    StartAtTop  is TRUE iff we should start at the top
  1504.  *                         of the document.
  1505.  *             FindDoc     points to the document being searched.
  1506.  *                         All the info we need is in fields in this doc.
  1507.  */
  1508. BOOL
  1509. DoFind (StartAtTop)
  1510.      BOOL StartAtTop;
  1511. {
  1512.   int CharPos;
  1513.   int iline;
  1514.   TypBlock far *BlockPtr;
  1515.   TypLine far *LinePtr;
  1516.   int found = FALSE;
  1517.   BOOL refresh = FALSE;
  1518.   int goline;
  1519.   unsigned int LineOrd;
  1520.   unsigned int LastAllowedLineOrd;
  1521.  
  1522.   CharPos = FindString (StartAtTop);
  1523.   if (CharPos >= 0)
  1524.     {
  1525.       iline = LineOnScreen (FindDoc, FindDoc->hFindBlock, FindDoc->FindOffset, FindDoc->FindLineID);
  1526.       /* If this line wasn't on the screen, we are going to have
  1527.        * to adjust the top of the screen.
  1528.        * Make the found line the top of the screen, then back up a
  1529.        * little to give the user a context in which to view the line.
  1530.        */
  1531.       if (iline == -1)
  1532.    {
  1533.      FindDoc->hCurTopScBlock = FindDoc->hFindBlock;
  1534.      FindDoc->TopScOffset = FindDoc->FindOffset;
  1535.      FindDoc->TopScLineID = FindDoc->FindLineID;
  1536.      refresh = TRUE;
  1537.      LockLine (FindDoc->hCurTopScBlock, FindDoc->TopScOffset, FindDoc->TopScLineID,
  1538.           &BlockPtr, &LinePtr);
  1539.      for (goline = FindDoc->ScYLines / 4; goline; goline--)
  1540.        {
  1541.          PrevLine (&BlockPtr, &LinePtr);
  1542.        }
  1543.      /* Have we gone past the top of the last screen?
  1544.            * If so, move the top line back to the top of the last screen.
  1545.            */
  1546.      LineOrd = WhatLine (BlockPtr, LinePtr);
  1547.      LastAllowedLineOrd = FindDoc->TotalLines - FindDoc->ScYLines;
  1548.      if (LineOrd > LastAllowedLineOrd)
  1549.        {
  1550.          GlobalUnlock (BlockPtr->hCurBlock);
  1551.          FindLineOrd (FindDoc, LastAllowedLineOrd, &BlockPtr, &LinePtr);
  1552.          LineOrd = LastAllowedLineOrd;
  1553.        }
  1554.      UnlockLine (BlockPtr, LinePtr, &(FindDoc->hCurTopScBlock),
  1555.             &(FindDoc->TopScOffset), &(FindDoc->TopScLineID));
  1556.      FindDoc->TopLineOrd = LineOrd;
  1557.      iline = LineOnScreen (FindDoc, FindDoc->hFindBlock, FindDoc->FindOffset, FindDoc->FindLineID);
  1558.    }
  1559.  
  1560.       InvalidateRect (FindDoc->hDocWnd, NULL, FALSE);
  1561.       found = TRUE;
  1562.     }
  1563.   return (found);
  1564. }
  1565. @
  1566.  
  1567.  
  1568. 1.8
  1569. log
  1570. @movebytes param changed from far * to huge *
  1571. @
  1572. text
  1573. @d4 1
  1574. a4 1
  1575.  * $Id: wvblock.c 1.7 1994/06/08 21:01:45 gardnerd Exp $
  1576. d6 3
  1577. d43 2
  1578. a44 1
  1579. #include "windows.h"
  1580. d47 1
  1581. @
  1582.  
  1583.  
  1584. 1.7
  1585. log
  1586. @more scrolling changes...
  1587. @
  1588. text
  1589. @d4 1
  1590. a4 1
  1591.  * $Id: wvblock.c 1.6 1994/06/01 19:04:02 gardnerd Exp $
  1592. d6 3
  1593. d1080 2
  1594. a1081 2
  1595.   char far *Source = FSource;
  1596.   char far *Target = FTarget;
  1597. @
  1598.  
  1599.  
  1600. 1.6
  1601. log
  1602. @horizontal scrolling support
  1603. @
  1604. text
  1605. @d4 1
  1606. a4 1
  1607.  * $Id: wvblock.c 1.5 1994/01/12 19:27:32 mrr Exp $
  1608. d6 3
  1609. a230 3
  1610.   MyBlock->OwnerDoc->LongestLine = max(MyBlock->OwnerDoc->LongestLine
  1611.                                        ,(unsigned)LineToAdd->length);
  1612.  
  1613. @
  1614.  
  1615.  
  1616. 1.5
  1617. log
  1618. @mrr mods 4
  1619. @
  1620. text
  1621. @d4 1
  1622. a4 1
  1623.  * $Id: wvblock.c 1.4 1993/12/08 01:27:21 rushing Exp $
  1624. d6 3
  1625. d227 3
  1626. @
  1627.  
  1628.  
  1629. 1.4
  1630. log
  1631. @new version box and cr lf consistency
  1632. @
  1633. text
  1634. @d4 1
  1635. a4 1
  1636.  * $Id: wvblock.c 1.3 1993/06/28 17:53:24 rushing Exp rushing $
  1637. d6 3
  1638. d62 1
  1639. a62 1
  1640.                CurBlockPtr->hNextBlock, CurBlockPtr->OwnerDoc);
  1641. d68 5
  1642. a72 5
  1643.     {
  1644.       MyNextBlock = (TypBlock far *) GlobalLock (MyBlock->hNextBlock);
  1645.       MyNextBlock->hPrevBlock = hMyBlock;
  1646.       GlobalUnlock (MyBlock->hNextBlock);
  1647.     }
  1648. d101 1
  1649. d163 2
  1650. a164 2
  1651.     {
  1652.       /* There is no next block, so we want to position the
  1653. d167 3
  1654. a169 3
  1655.       PrevLine (CurBlockPtr, CurLinePtr);
  1656.       NextLine (CurBlockPtr, CurLinePtr);
  1657.     }
  1658. d232 1
  1659. a232 1
  1660.          ((char far *) *CurAddPtr) + LineToAdd->length,
  1661. d235 1
  1662. a235 1
  1663.          LineToAdd->length);
  1664. d240 1
  1665. d254 20
  1666. a273 20
  1667.     {
  1668.       /* We're at end of block; create a new empty one.           */
  1669.       /* This will be the current block, so release references    */
  1670.       /* to the now-current block                                 */
  1671.       if (NewBlock (MyBlock, CurBlockPtr))
  1672.         {
  1673.           return (1);
  1674.         }
  1675.       else
  1676.         {
  1677.           GlobalUnlock (MyBlock->hCurBlock);
  1678.           *CurAddPtr = (TypLine far *)
  1679.         ((char far *) *CurBlockPtr + sizeof (TypBlock));
  1680.           /* Now we can recursively try again to add the line.     */
  1681.           if (AddLine (LineToAdd, CurBlockPtr, CurAddPtr))
  1682.         {
  1683.           return (1);
  1684.         }
  1685.         }
  1686.     }
  1687. d275 70
  1688. a344 70
  1689.     {
  1690.       /* We need to split the textblock.                          */
  1691.       /* Find a place to split the block by starting at the       */
  1692.       /* beginning of the block and skipping through the lines    */
  1693.       /* until we pass the number of bytes that marks the         */
  1694.       /* split point.  The previous line is the split point.      */
  1695.  
  1696.       TypLine far *MyLinePtr = (TypLine far *) ((char far *) MyBlock + sizeof (TypBlock));
  1697.       TypLine far *MyLastLine = MyLinePtr;
  1698.       int nOldLines = 0, nBytesMoved, MyAddOffset;
  1699.  
  1700.       while ( (unsigned)((char far *) MyLinePtr - (char far *) MyBlock) <
  1701.          MyBlock->OwnerDoc->SplitSize &&
  1702.          MyLinePtr->length != END_OF_BLOCK)
  1703.         {
  1704.           nOldLines++;
  1705.           MyLastLine = MyLinePtr;
  1706.           IncPtr (MyLinePtr, MyLinePtr->length);
  1707.         }
  1708.  
  1709.       /* Allocate the new block and copy the last portion of      */
  1710.       /* the current block to the new one.   The range to         */
  1711.       /* copy starts at the above-determined split point and      */
  1712.       /* goes until the LWA+1.                                    */
  1713.       /* Then adjust the new & old textblock fields.              */
  1714.  
  1715.       if (NewBlock (MyBlock, &NewBlockPtr))
  1716.         {
  1717.           return (1);
  1718.         }
  1719.       else
  1720.         {
  1721.           MoveBytes (MyLastLine, (char far *) NewBlockPtr + sizeof (TypBlock),
  1722.              nBytesMoved = (((char far *) MyBlock + MyBlock->LWAp1)) - (char far *) MyLastLine);
  1723.           MyBlock->LWAp1 = (char far *) MyLastLine - ((char far *) MyBlock)
  1724.         + sizeof (TypLine);
  1725.           ((TypLine far *) MyLastLine)->length = END_OF_BLOCK;
  1726.           ((TypLine far *) MyLastLine)->LineID = NextLineID++;
  1727.           NewBlockPtr->NumLines = MyBlock->NumLines - nOldLines;
  1728.           MyBlock->NumLines = nOldLines;
  1729.           NewBlockPtr->LWAp1 = nBytesMoved + sizeof (TypBlock);
  1730.  
  1731.           /* Should the new line go in the old block or the new?   */
  1732.           /* If the add point is beyond the end of the newly-      */
  1733.           /* truncated block, we must move the add point to the    */
  1734.           /* next block and make the new block the current one.    */
  1735.           /* The new position should be the same                   */
  1736.           /* number of line bytes past the beginning of the next   */
  1737.           /* block as it was past the split point when it was in   */
  1738.           /* the old block.                                        */
  1739.           /* Either way, one block (the old or the new one)        */
  1740.           /* must be unlocked.                                     */
  1741.  
  1742.           if (*CurAddPtr >= MyLastLine)
  1743.         {
  1744.           /* Add point is in new block.                         */
  1745.  
  1746.           MyAddOffset = (char far *) *CurAddPtr - (char far *) MyLastLine + sizeof (TypBlock);
  1747.           *CurAddPtr = (TypLine far *) ((char far *) NewBlockPtr + MyAddOffset);
  1748.           *CurBlockPtr = NewBlockPtr;
  1749.           GlobalUnlock (MyBlock->hCurBlock);
  1750.         }
  1751.           else
  1752.         {
  1753.           /* Add point is in current block.                     */
  1754.           GlobalUnlock (NewBlockPtr->hCurBlock);
  1755.         }
  1756.           return (AddLine (LineToAdd, CurBlockPtr, CurAddPtr));
  1757.         }
  1758.     }
  1759. d399 1
  1760. a399 1
  1761.     (char far *) MyLinePtr - MyLinePtr->length;
  1762. d404 1
  1763. a404 1
  1764.          LineToAdd->length);
  1765. d424 7
  1766. a430 7
  1767.          MyBlockPtr->OwnerDoc->SplitSize &&
  1768.          MyLinePtr->length != END_OF_BLOCK)
  1769.     {
  1770.       nOldLines++;
  1771.       MyLastLine = MyLinePtr;
  1772.       IncPtr (MyLinePtr, MyLinePtr->length);
  1773.     }
  1774. d439 3
  1775. a441 3
  1776.     {
  1777.       return (1);
  1778.     }
  1779. d443 38
  1780. a480 38
  1781.     {
  1782.       MoveBytes (MyLastLine, (char far *) NewBlockPtr + sizeof (TypBlock),
  1783.              nBytesMoved = (((char far *) MyBlockPtr + MyBlockPtr->LWAp1)) - (char far *) MyLastLine);
  1784.       MyBlockPtr->LWAp1 = (char far *) MyLastLine - ((char far *) MyBlockPtr)
  1785.         + sizeof (TypLine);
  1786.       ((TypLine far *) MyLastLine)->length = END_OF_BLOCK;
  1787.       ((TypLine far *) MyLastLine)->LineID = NextLineID++;
  1788.       NewBlockPtr->NumLines = MyBlockPtr->NumLines - nOldLines;
  1789.       MyBlockPtr->NumLines = nOldLines;
  1790.       NewBlockPtr->LWAp1 = nBytesMoved + sizeof (TypBlock);
  1791.  
  1792.       /* Should this line go in the old block or the new?   */
  1793.       /* If the add point is beyond the end of the newly-      */
  1794.       /* truncated block, we must move the add point to the    */
  1795.       /* next block and make the new block the current one.    */
  1796.       /* The new position should be the same                   */
  1797.       /* number of line bytes past the beginning of the next   */
  1798.       /* block as it was past the split point when it was in   */
  1799.       /* the old block.                                        */
  1800.       /* Either way, one block (the old or the new one)        */
  1801.       /* must be unlocked.                                     */
  1802.  
  1803.       if (*CurLinePtr >= MyLastLine)
  1804.         {
  1805.           /* Replace point is in new block.                         */
  1806.  
  1807.           MyAddOffset = (char far *) *CurLinePtr - (char far *) MyLastLine + sizeof (TypBlock);
  1808.           *CurLinePtr = (TypLine far *) ((char far *) NewBlockPtr + MyAddOffset);
  1809.           *CurBlockPtr = NewBlockPtr;
  1810.           GlobalUnlock (MyBlockPtr->hCurBlock);
  1811.         }
  1812.       else
  1813.         {
  1814.           /* Add point is in current block.                     */
  1815.           GlobalUnlock (NewBlockPtr->hCurBlock);
  1816.         }
  1817.       return (ReplaceLine (LineToAdd, CurBlockPtr, CurLinePtr));
  1818.     }
  1819. d523 1
  1820. a523 1
  1821.          bytes_to_copy);
  1822. d545 1
  1823. a545 1
  1824.     {
  1825. d547 1
  1826. a547 1
  1827.       /* We have emptied the block.  We must check for whether
  1828. d550 3
  1829. a552 3
  1830.       if (MyBlockPtr->OwnerDoc->TotalLines)
  1831.         {
  1832.           /* The document is not empty.  Delete this empty block.
  1833. d554 5
  1834. a558 5
  1835.           DeleteBlock (CurBlockPtr, CurLinePtr);
  1836.         }
  1837.       else
  1838.         {
  1839.           /* The document is empty.  Don't delete this block.
  1840. d562 2
  1841. a563 2
  1842.         }
  1843.     }
  1844. d565 2
  1845. a566 2
  1846.     {
  1847.       /* We're at the end of the block, but the block is not empty.
  1848. d569 2
  1849. a570 2
  1850.       NextLine (CurBlockPtr, CurLinePtr);
  1851.     }
  1852. d607 6
  1853. a612 6
  1854.     {
  1855.       GlobalUnlock ((*BlockPtr)->hCurBlock);
  1856.       *BlockPtr = (TypBlock far *) GlobalLock ((*BlockPtr)->hNextBlock);
  1857.       *LinePtr = (TypLine far *) ((char far *) *BlockPtr + sizeof (TypBlock));
  1858.       retcode = 1;
  1859.     }
  1860. d651 5
  1861. a655 5
  1862.     {
  1863.       GlobalUnlock ((*BlockPtr)->hCurBlock);
  1864.       *BlockPtr = (TypBlock far *) GlobalLock ((*BlockPtr)->hPrevBlock);
  1865.       *LinePtr = (TypLine far *)
  1866.         ((char far *) *BlockPtr + (*BlockPtr)->LWAp1 - sizeof (TypLine));
  1867. d657 2
  1868. a658 2
  1869.       IncPtr (*LinePtr, -(*((int far *) (*LinePtr) - 1)));
  1870.     }
  1871. d660 3
  1872. a662 3
  1873.     {
  1874.       return (0);
  1875.     }
  1876. d720 6
  1877. a725 6
  1878.     {
  1879.       bptr = (char far *) LinePtr + sizeof (TypLine) + sizeof (TypGroup);
  1880.       while (--BufSize > 1 && (*(Buf++) = *(bptr++)));
  1881.       *Buf = '\0';
  1882.       DidIt = TRUE;
  1883.     }
  1884. d727 6
  1885. a732 6
  1886.     {
  1887.       bptr = (char far *) LinePtr + sizeof (TypLine) + sizeof (TypText);
  1888.       while (--BufSize > 1 && (*(Buf++) = *(bptr++)));
  1889.       *Buf = '\0';
  1890.       DidIt = TRUE;
  1891.     }
  1892. d785 4
  1893. a788 4
  1894.     {
  1895.       *BlockPtr = MyBlockPtr;
  1896.       *LinePtr = MyLinePtr;
  1897.     }
  1898. d790 4
  1899. a793 4
  1900.     {
  1901.       MessageBox (hWndConf, "Can't find line", "in LockLine", MB_ICONHAND | MB_OK);
  1902.       return (FALSE);
  1903.     }
  1904. d877 5
  1905. a881 1
  1906. {
  1907. d900 4
  1908. a903 4
  1909.     {
  1910.       MessageBox (MyDoc->hDocWnd, "Hit end of document", "Error in WhatLine",
  1911.               MB_OK | MB_ICONHAND);
  1912.     }
  1913. d925 16
  1914. a940 1
  1915.  
  1916. d995 4
  1917. d1009 3
  1918. a1011 3
  1919.       if (LinesSoFar + MyBlockPtr->NumLines > LineOrd)
  1920.     break;
  1921.       LinesSoFar += MyBlockPtr->NumLines;
  1922. d1021 1
  1923. d1023 5
  1924. a1027 5
  1925.     {
  1926.       LinesSoFar++;
  1927.       if (!NextLine (&MyBlockPtr, &MyLinePtr))
  1928.         break;
  1929.     }
  1930. d1032 22
  1931. d1079 1
  1932. a1079 1
  1933.     *(Target--) = *(Source--);
  1934. d1084 1
  1935. a1084 1
  1936.     *(Target++) = *(Source++);
  1937. d1212 13
  1938. a1224 13
  1939.     {
  1940.       old_lineID = LinePtr->LineID;
  1941.       lpfnFunc (Doc, &BlockPtr, &LinePtr, wFlag, wValue);
  1942.       if (old_lineID == LinePtr->LineID &&
  1943.           LinePtr->length != END_OF_BLOCK)
  1944.         {
  1945.           looping = NextLine (&BlockPtr, &LinePtr);
  1946.         }
  1947.       else if (LinePtr->length == END_OF_BLOCK)
  1948.         {
  1949.           looping = FALSE;
  1950.         }
  1951.     }
  1952. d1232 55
  1953. d1359 10
  1954. a1368 8
  1955.     {
  1956.       orglineptr = (char far *) LinePtr + TextOffset;
  1957.       sourceptr = sourceline;
  1958.       for (SourceLen = 0; ch = *(orglineptr),
  1959.            *(sourceptr++) = tolower (ch); SourceLen++)
  1960.         orglineptr++;
  1961.       found = SearchLine (sourceline, SourceLen, targline, TargLen);
  1962.     }
  1963. d1408 4
  1964. a1411 4
  1965.     {
  1966.       targptr++;
  1967.       searchptr++;
  1968.     }
  1969. d1413 3
  1970. a1415 3
  1971.     {
  1972.       return (lineptr - Line);
  1973.     }
  1974. d1454 12
  1975. a1465 12
  1976.     {
  1977.       FindDoc->hCurTopScBlock = FindDoc->hFindBlock;
  1978.       FindDoc->TopScOffset = FindDoc->FindOffset;
  1979.       FindDoc->TopScLineID = FindDoc->FindLineID;
  1980.       refresh = TRUE;
  1981.       LockLine (FindDoc->hCurTopScBlock, FindDoc->TopScOffset, FindDoc->TopScLineID,
  1982.             &BlockPtr, &LinePtr);
  1983.       for (goline = FindDoc->ScYLines / 4; goline; goline--)
  1984.         {
  1985.           PrevLine (&BlockPtr, &LinePtr);
  1986.         }
  1987.       /* Have we gone past the top of the last screen?
  1988. d1468 13
  1989. a1480 13
  1990.       LineOrd = WhatLine (BlockPtr, LinePtr);
  1991.       LastAllowedLineOrd = FindDoc->TotalLines - FindDoc->ScYLines;
  1992.       if (LineOrd > LastAllowedLineOrd)
  1993.         {
  1994.           GlobalUnlock (BlockPtr->hCurBlock);
  1995.           FindLineOrd (FindDoc, LastAllowedLineOrd, &BlockPtr, &LinePtr);
  1996.           LineOrd = LastAllowedLineOrd;
  1997.         }
  1998.       UnlockLine (BlockPtr, LinePtr, &(FindDoc->hCurTopScBlock),
  1999.               &(FindDoc->TopScOffset), &(FindDoc->TopScLineID));
  2000.       FindDoc->TopLineOrd = LineOrd;
  2001.       iline = LineOnScreen (FindDoc, FindDoc->hFindBlock, FindDoc->FindOffset, FindDoc->FindLineID);
  2002.     }
  2003. @
  2004.  
  2005.  
  2006. 1.3
  2007. log
  2008. @fixed compiler warnings
  2009. @
  2010. text
  2011. @d1 1
  2012. d4 1
  2013. a4 1
  2014.  * $Id: wvblock.c 1.2 1993/05/24 23:56:18 rushing Exp rushing $
  2015. d6 3
  2016. @
  2017.  
  2018.  
  2019. 1.2
  2020. log
  2021. @Doc->HeaderLines = 0 (MRB)
  2022. @
  2023. text
  2024. @d3 1
  2025. a3 1
  2026.  * $Id: wvblock.c 1.1 1993/02/16 20:53:50 rushing Exp $
  2027. d5 3
  2028. d277 2
  2029. a278 1
  2030.       while ((char far *) MyLinePtr - (char far *) MyBlock < MyBlock->OwnerDoc->SplitSize &&
  2031. d414 2
  2032. a415 1
  2033.       while (((char far *) MyLinePtr - (char far *) MyBlockPtr) < MyBlockPtr->OwnerDoc->SplitSize &&
  2034. @
  2035.  
  2036.  
  2037. 1.1
  2038. log
  2039. @Initial revision
  2040. @
  2041. text
  2042. @d3 4
  2043. a6 2
  2044.  * $Id$
  2045.  * $Log$
  2046. d8 1
  2047. d1044 1
  2048. @
  2049.